﻿/* Muaz Khan – http://dashingquill.web.officelive.com */
/***********************************
* All reusable helper function goes in the "dashingquill" object
***********************************/
var dashingquill = window.dashingquill || {};

dashingquill = ( function ()
{
    /***********************************
    * Using rich cross-browser Sizzle search library
    ***********************************/
    var sz = Sizzle;

    /***********************************
    * For solving absolute URL issues: http://dashingquill.web.officelive.com/blogs/2011/Absolute-or-Relative-URL-issues-and-solution-for-CSS-and-JavaScript.html
    ***********************************/
    var domainName = location.protocol + '//' + location.host;

    /***********************************
    * Search by selector within context
    ***********************************/
    var find = function ( selector, context )
    {
        if ( selector.substring( 0, 1 ) == '#' )
            return sz( selector, context )[0];
        else
            return sz( selector, context );
    };

    /***********************************
    * Iterate over array and return user friendly object from each index
    ***********************************/
    var each = function ( arr, callback )
    {
        var length = arr.length;
        for ( var i = 0; i < length; i++ )
        {
            callback(arr[i], i);
        }
    };

    /***********************************
    * Bind any event by leveraging cross-browsers
    ***********************************/
    var bind = function ( obj, eventName, callback )
    {
        var addEvent = function ( elm, evType, fn, useCapture )
        {
            if ( elm.addEventListener )
            {
                elm.addEventListener( evType, fn, useCapture );
                return true;
            }
            else if ( elm.attachEvent )
            {
                return elm.attachEvent( 'on' + evType, fn );
            }
            else
            {
                elm['on' + evType] = fn;
            }
            return this;
        };

        if ( typeof obj == 'string' ) obj = find( obj );

        if ( obj && obj.length != undefined )
        {
            each( obj, function ( elem )
            {
                addEvent( elem, eventName, function ( e )
                {
                    callback( elem, e );
                }, false );
            } );
        }
        else if ( obj && typeof obj == 'object' ) addEvent( obj, eventName, function ( e )
        {
            callback( obj, e );
        }, true );
    };

    /***********************************
    * XMLHttpRequest: For leveraging cross-browsers; we are using XMLHttpReqeust.js file too!!
    ***********************************/
    var xhr = function ( obj )
    {
        var request = new XMLHttpRequest();

        request.onreadystatechange = function ()
        {
            if ( request.readyState == 4 && request.status == 200 )
            {
                if (obj.type) obj.callback(request.responseText);
                else obj.callback( JSON.parse( request.responseText ) );
            }
        };
        request.open( obj.type || 'POST', obj.url );
        request.send( null );
    };

    /***********************************
    * Search URLs from within text; and linkify those URLs
    ***********************************/
    var linkify = function ( text )
    {
        var first, second, third, fourth;
        second = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
        first = text.replace( second, '<a href="$1" target="_blank" follow="nofollow" class="external">$1</a>' );
        third = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
        first = first.replace( third, '$1<a href="http://$2" target="_blank" follow="nofollow" class="external">$2</a>' );
        fourth = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
        first = first.replace( fourth, '<a href="mailto:$1" target="_blank" follow="nofollow" class="external">$1</a>' );
        return first;
    };

    /***********************************
    * Run some code after specific interval
    ***********************************/
    var once = function ( delay, callback )
    {
        var counter = 0;
        var time = window.setInterval( function ()
        {
            counter++;
            if ( counter >= delay )
            {
                callback();
                window.clearInterval( time );
            }
        }, 100 );
    };

    /***********************************
    * For HTML5 supported web-browsers; using CSS3 transition for Sliding-Down effect; 
    * in contrast; for IE: just display the element
    ***********************************/
    var show = function ( elem, value )
    {
        if ( typeof elem == 'string' ) elem = find( elem );

        if ( elem && elem.length != undefined )
        {
            each( elem, function ( em )
            {
                if ( value ) em.style.display = value;
                else em.style.display = 'block';
            } );
        }
        else if (elem && typeof elem == 'object' )
        {
            if ( value ) elem.style.display = value;
            else elem.style.display = 'block';
        }
        return this;
    };

    /***********************************
    * For HTML5 supported web-browsers; using CSS3 transition for Sliding-Up effect; 
    * in contrast; for IE: just hide the element
    ***********************************/
    var hide = function ( elem )
    {
        if ( typeof elem == 'string' ) elem = find( elem );
        if (elem && elem.length != undefined )
        {
            each( elem, function ( e )
            {
                e.style.display = 'none';
            } );
        }
        else if (elem && typeof elem == 'object' ) elem.style.display = 'none';
        return this;
    };


    /***********************************
    * A way of setting innerHTML
    ***********************************/
    var html = function ( elem, value )
    {
        if ( typeof elem == 'string' ) elem = find( elem );
        elem.innerHTML = value;
        return this;
    };

    /***********************************
    * Focus specific element
    ***********************************/
    var focus = function ( elem )
    {
        if ( typeof elem == 'string' ) elem = find( elem );
        elem.focus();
        return this;
    };

    /***********************************
    * Append element to the beginning
    ***********************************/
    var prepend = function ( parent, elementToPrepend )
    {
        return parent.insertBefore( elementToPrepend, parent.firstChild );
    };

    /***********************************
    * handles 1) new-lines [\n] 2) HTML tags [<>] 3) Ampersand [&] 4) bold [<br />] and 5) italic [<i />]
    ***********************************/
    var validate = function ( value )
    {
        value = value
            .replace(/-/g, '__')
            .replace(/\?/g, '-qmark')
            .replace(/ /g, '--')
            .replace(/\n/g, '-n')
            .replace(/</g, '-lt')
            .replace(/>/g, '-gt')
            .replace(/&/g, '-amp')
            .replace(/#/g, '-nsign')
            .replace(/__t-n/g, '__t');
        return value;
    };

    /***********************************
    * Handle master-page or layout-page related stuff
    ***********************************/
    var handleLayout = function ()
    {
        /***********************************
        * handle menu clicks
        ***********************************/
        bind( '.menu div, #account-settings, #logout', 'click', function ( menu, e )
        {
            stopBubbling( e );
            var checkid = function ( id, navigateTo )
            {
                if ( menu.id == id ) window.location = domainName + navigateTo;
            };

            checkid( 'help', '/About-Muaz-Khan' );
            checkid( 'home', '/HomePage' );
            checkid( 'search', '/UsersList' );
            checkid('account-settings', '/AccountSettings');
            checkid('circles', '/Circles');

            if ( menu.id == 'login' ) /*window.location = domainName + '/account';*/
            {
                var accountSettings = find('#account-settings');
                if (accountSettings == undefined) location = '/login';
                else show('#user-settings');
            }
            if ( menu.id == 'logout' )
            {
                xhr( {
                    url: '/logout',
                    callback: function ( response )
                    {
                        if ( response == true ) window.location = domainName;
                        else alert( response );
                    }
                } );
            }
            checkid('user-homepage-link', '/' + menu.getAttribute('accesskey'));
        } );

        /***********************************
        * Handling BODY/Document click event to hide all context menus [if visible]
        ***********************************/
        bind( document, 'click', function ()
        {
            var postOptions = sz('.post-options');
            hide(postOptions);
            each(postOptions, function (postOption) {
                postOption.style.marginLeft = '782px';
            });
            hide('.user-settings');
            var aboutUser = find('#about-user');
            if (aboutUser) hide(aboutUser);

            var shareTo = find('#share-to');
            if (shareTo)hide(shareTo);

            var circlesContextMenu = find('#circles-context-menu');
            if (circlesContextMenu) {
                hide(circlesContextMenu);                
            }
            var addMore = find('#add-more');
            if (addMore) {
                addMore.innerHTML = '+ Add people to share';
                addMore.style.padding = '5px 10px';
            }
        } );
    };

    /***********************************
    * Preventing Events' Bubbling
    ***********************************/
    var stopBubbling = function ( e )
    {
        if ( e.preventDefault ) e.preventDefault();
        else if ( e.stopPropagation ) e.stopPropagation();
        else e.cancelBubble = true;
    };

    return {
        bind: function ( obj, eventName, callback )
        {
            return bind( obj, eventName, callback );
        },
        find: function ( selector, context )
        {
            return find( selector, context );
        },
        once: function ( delay, callback )
        {
            return once( delay, callback );
        },
        xhr: function ( parameters )
        {
            return xhr( parameters );
        },
        each: function ( arr, callback )
        {
            return each( arr, callback );
        },
        linkify: function ( text )
        {
            return linkify( text );
        },
        show: function ( elem, value )
        {
            return show( elem, value );
        },
        hide: function ( elem )
        {
            return hide( elem );
        },
        html: function ( elem, value )
        {
            return html( elem, value );
        },
        focus: function ( elem )
        {
            return focus( elem );
        },
        domainName: domainName,
        validate: function ( value )
        {
            return validate( value );
        },
        handleLayout: function ()
        {
            return handleLayout();
        },
        prepend: function ( parent, elementToPrepend )
        {
            return prepend( parent, elementToPrepend );
        },
        stopBubbling: function ( e )
        {
            return stopBubbling( e );
        }
    };
} )( dashingquill );

// Add ECMA262-5 string trim if not supported natively
// Not used in this project, anywhere !!!!!! --- instead used .NET's own String.Trim() --- cross browser !!!
if ( !( 'trim' in String.prototype ) )
{
    String.prototype.trim = function ()
    {
        return this.replace( /^\s+/, '' ).replace( /\s+$/, '' );
    };
}